﻿#region Copyright information
// 
// Copyright © 2012-2013 Yongkee Cho. All rights reserved.
// 
// This code is a part of the SubnetworkToolkit and governed under the terms of the
// GNU Lesser General  Public License (LGPL) version 2.1 which accompanies this distribution.
// For more information on the LGPL, please visit http://bol.codeplex.com/license.
// 
// - Filename: Network.cs
// - Author: Yongkee Cho
// - Email: yongkeecho@outlook.com
// - Date Created: 2013-01-30 2:55 PM
// - Last Modified: 2013-01-30 3:21 PM
// 
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using BOL.Linq;

namespace SubnetworkToolkit
{
    public class Network : List<Gene>, IEquatable<Network>
    {
        private readonly double _mean;
        private readonly IList<int> _bypass;
 
        #region Constructors

        public Network(IEnumerable<Gene> genes, double mean = -1.0)
            : this(genes, new List<int>(), mean)
        { }

        public Network(IEnumerable<Gene> genes, IList<int> bypass, double mean = -1.0)
            : base(genes)
        {
            _bypass = bypass;
            _mean = mean;
        }

        #endregion

        public double Mean
        {
            get { return _mean < 0 ? this.Where(x => !_bypass.Contains(x.Id)).Average(x => Math.Abs(x.Statistic)) : _mean; }
        }

        public double FractionMean(double fraction)
        {
            var k = (int)(Count * fraction);

            return k > 0 ? 
                this.Select(x => Math.Abs(x.Statistic)).OrderByDescending(x => x).Take(k).Average(x => x) :
                this.Average(x => Math.Abs(x.Statistic));
        }

        #region Annotation

        //public void Annotate()
        //{
        //    var annotations = new Annotations_Human();

        //    foreach (var gene in Dictionary.Keys)
        //    {
        //        try
        //        {
        //            var gi = annotations.GeneInfo.Single(x => x.ID.Equals(Convert.ToInt32(gene.Id)));
        //            gene.Name = gi.Symbol;
        //            if (!String.IsNullOrEmpty(gi.Alternatives))
        //                gene.Alternatives = gi.Alternatives.Split('|');
        //            if (!String.IsNullOrEmpty(gi.Chromosome))
        //                gene.Chromosome = GetChromosome(gi.Chromosome);
        //            if (!String.IsNullOrEmpty(gi.Cytoband))
        //                gene.CytoBand = CytoBand.Parse(gi.Cytoband);
        //            if (gi.GeneType != 0)
        //                gene.Type = GetGeneType(gi.GeneType);
        //            if (!String.IsNullOrEmpty(gi.FullName))
        //                gene.FullName = gi.FullName;
        //        }
        //        catch (Exception ex)
        //        {
        //            Console.WriteLine(ex.Message);
        //        }
        //    }
        //}

        //private Chromosome GetChromosome(string chrStr)
        //{
        //    return new Chromosome(chrStr);
        //}

        //private static GeneType GetGeneType(short type)
        //{
        //    switch (type)
        //    {
        //        case 1:
        //            return GeneType.ProteinCoding;
        //        case 2:
        //            return GeneType.Pseudo;
        //        case 3:
        //            return GeneType.RibosomalRna;
        //        case 4:
        //            return GeneType.TransferRna;
        //        case 5:
        //            return GeneType.SmallCytoplasmicRna;
        //        case 6:
        //            return GeneType.SmallNucleolarRna;
        //        case 7:
        //            return GeneType.SmallNuclearRna;
        //        case 8:
        //            return GeneType.NonCodingRna;
        //        case 9:
        //            return GeneType.MiscellaneousRna;
        //        case 10:
        //            return GeneType.Other;
        //        default:
        //            return GeneType.Unknown;
        //    }
        //}

        #endregion

        #region IEquatable<Network> implementation

        public bool Equals(Network other)
        {
            return this.SetEquals(other);
        }

        #endregion

        #region Object overriden

        public override int GetHashCode()
        {
            return this.Aggregate(1, (hashCode, gene) => hashCode ^ gene.Id);
        }

        public override bool Equals(object other)
        {
            if (other == null)
                throw new ArgumentNullException();

            if (!(other is Network))
                throw new InvalidCastException("The 'other' argument is not a Network object.");

            return Equals(other as Network);
        }

        public override string ToString()
        {
            return String.Format("{0}: {1:0.0000}", Count, Mean);
        }

        #endregion
    }
}